package com.kakarote.examine.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.kakarote.core.common.enums.FieldEnum;
import com.kakarote.core.exception.CrmException;
import com.kakarote.core.feign.crm.entity.ExamineField;
import com.kakarote.core.feign.examine.entity.ExamineConditionDataBO;
import com.kakarote.core.feign.examine.entity.ExamineFlowConditionDataVO;
import com.kakarote.core.feign.examine.entity.ExamineFlowFieldUpdateLogBO;
import com.kakarote.core.feign.examine.entity.ExamineUpdateFieldBO;
import com.kakarote.core.feign.oa.OaService;
import com.kakarote.core.feign.oa.entity.OaExamineTravel;
import com.kakarote.examine.common.LanguageFieldUtil;
import com.kakarote.examine.constant.ExamineCodeEnum;
import com.kakarote.examine.entity.PO.Examine;
import com.kakarote.examine.entity.PO.ExamineFlowAuthField;
import com.kakarote.examine.entity.PO.ExamineFlowFieldUpdateLog;
import com.kakarote.examine.entity.PO.ExamineRecord;
import com.kakarote.examine.service.ExamineModuleService;
import com.kakarote.examine.service.IExamineRecordService;
import com.kakarote.examine.service.IExamineService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author JiaS
 * @date 2020/12/19
 */
@Slf4j
@Service("examineOaService")
public class ExamineOaServiceImpl implements ExamineModuleService {

    @Autowired
    private IExamineRecordService examineRecordService;

    @Autowired
    private IExamineService examineService;

    @Autowired
    private OaService oaService;

    @Override
    public List<ExamineField> queryExamineField(Integer label, Long categoryId) {
        if (categoryId == null) {
            return new ArrayList<>();
        }
        List<ExamineField> examineFields = oaService.queryExamineField(categoryId).getData();
        Examine examine = examineService.getById(categoryId);
        if (CollectionUtil.isNotEmpty(examineFields)) {
            for (ExamineField examineField : examineFields) {
                examineField.setFieldName(StrUtil.toCamelCase(examineField.getFieldName()));
                Map<String, String> keyMap = LanguageFieldUtil.getFieldNameKeyMap("name_resourceKey", "customField.oaExamine" + examine.getOaType() + ".", examineField.getFieldName(), examineField.getSetting());
                Map<String, String> remarksKey = LanguageFieldUtil.getFieldNameKeyMap("remarks_resourceKey", "customField.oaExamine" + examine.getOaType() + ".", examineField.getFieldName());
                keyMap.putAll(remarksKey);
                examineField.setLanguageKeyMap(keyMap);
            }
        }
        return examineFields;
    }

    @Override
    public void updateCheckStatus(Integer label, Long typeId, Integer checkStatus, Object data) {
        ExamineConditionDataBO examineConditionDataBO = new ExamineConditionDataBO();
        examineConditionDataBO.setLabel(label);
        examineConditionDataBO.setTypeId(typeId);
        examineConditionDataBO.setCheckStatus(checkStatus);
        oaService.updateCheckStatusByNewExamine(examineConditionDataBO);
    }

    @Override
    public void checkStatus(Integer label, Long typeId, Integer checkStatus, Integer oldCheckStatus) {
        int four = 4;
        if (checkStatus == four) {
            //当前审核已通过不可撤回
            if (oldCheckStatus == 1) {
                throw new CrmException(ExamineCodeEnum.EXAMINE_RECHECK_PASS_ERROR);
            }
        }
    }

    @Override
    public Map<String, Object> getConditionMap(Integer label, Long typeId, Long recordId) {
        ExamineRecord record = examineRecordService.getById(recordId);
        if (record == null) {
            log.error("没有找到对应的审核记录！查找的记录id为{}", recordId);
            return new HashMap<>(2);
        }
        ExamineConditionDataBO examineConditionDataBO = new ExamineConditionDataBO();
        examineConditionDataBO.setLabel(label);
        examineConditionDataBO.setTypeId(typeId);
        Long examineId = record.getExamineId();
        examineConditionDataBO.setCategoryId(examineId);
        List<String> fieldList = new ArrayList<>();
        List<ExamineFlowConditionDataVO> conditionDataVoS = examineService.previewFiledName(label, recordId, null);
        if (conditionDataVoS != null) {
            fieldList = conditionDataVoS.stream().map(ExamineFlowConditionDataVO::getFieldName).collect(Collectors.toList());
            fieldList.removeIf(StrUtil::isEmpty);
        }
        examineConditionDataBO.setFieldList(fieldList);
        return oaService.getDataMapForNewExamine(examineConditionDataBO).getData();
    }


    /**
     * 获取成员组件需要的数据entity
     *
     * @param fieldName
     * @param label
     * @param typeId
     * @param recordId
     * @return
     */
    @Override
    public Map<String, Object> getMemberComponentMap(String fieldName, Integer label, Long typeId, Long recordId) {
        ExamineRecord record = examineRecordService.getById(recordId);
        ExamineConditionDataBO examineConditionDataBO = new ExamineConditionDataBO();
        examineConditionDataBO.setLabel(label);
        examineConditionDataBO.setTypeId(typeId);
        examineConditionDataBO.setCategoryId(record.getExamineId());
        examineConditionDataBO.setFieldList(CollUtil.toList(fieldName));
        return oaService.getDataMapForNewExamine(examineConditionDataBO).getData();
    }


    @Override
    public List<?> getAuthField(List<ExamineFlowAuthField> authFields, Integer label, Long typeId, List<ExamineFlowFieldUpdateLog> updateLogs) {
        List<Map<String, Object>> data = oaService.queryFieldInfo(label, typeId).getData();

        for (Map<String, Object> datum : data) {
            Object type = datum.get("type");
            if (FieldEnum.EXAMINE_CAUSE.getType().equals(type) || FieldEnum.BUSINESS_CAUSE.getType().equals(type)) {
                List<String> filedList = new ArrayList<>();
                if (FieldEnum.EXAMINE_CAUSE.getType().equals(type)) {
                    //差旅
                    filedList = new ArrayList<String>() {{
                        add("startAddress");
                        add("endAddress");
                        add("startTime");
                        add("endTime");
                        add("traffic");
                        add("stay");
                        add("diet");
                        add("other");
                        add("money");
                        add("description");
                        add("file");
                    }};
                }

                //出差
                if (FieldEnum.BUSINESS_CAUSE.getType().equals(type)) {
                    filedList = new ArrayList<String>() {{
                        add("vehicle");
                        add("trip");
                        add("startAddress");
                        add("endAddress");
                        add("startTime");
                        add("endTime");
                        add("description");
                    }};

                }

                List<Map<String, Object>> fieldExtendList = new ArrayList<>();
                OaExamineTravel travel = new OaExamineTravel();
                Map<String, Object> map = BeanUtil.beanToMap(travel);
                List<String> finalFiledList = filedList;
                map.forEach((k, v) -> {
                    Map<String, Object> fieldMap = new HashMap<>();
                    if (finalFiledList.contains(k)) {
                        fieldMap.put("fieldName", k);
                        fieldMap.put("authLevel", 2);
                        fieldExtendList.add(fieldMap);
                    }
                });
                datum.put("fieldExtendList", fieldExtendList);

            }
        }


        if (CollectionUtil.isNotEmpty(authFields)) {
            List<Map<String, Object>> list = new ArrayList<>();
            Map<String, ExamineFlowAuthField> collect = authFields.stream().filter(authField -> authField.getAuthLevel() > 1).collect(Collectors.toMap(
                    e -> StrUtil.toCamelCase(e.getFieldName()), Function.identity(), (k1, k2) -> k1
            ));
            Set<String> keySet = collect.keySet();

            for (Map<String, Object> datum : data) {
                if (keySet.contains(datum.get("fieldName"))) {
                    Object type = datum.get("type");
                    ExamineFlowAuthField authField = collect.get(datum.get("fieldName"));
                    datum.put("authLevel", authField.getAuthLevel());
                    datum.put("tableLevel", authField.getTableLevel());
                    if (FieldEnum.DETAIL_TABLE.getType().equals(type) || FieldEnum.EXAMINE_CAUSE.getType().equals(type) || FieldEnum.BUSINESS_CAUSE.getType().equals(type)) {
                        disposeDetailTable(datum, authField.getFieldExtendList());
                    }

                    list.add(datum);
                }
            }

            for (ExamineFlowFieldUpdateLog updateLog : updateLogs) {
                String fieldName = updateLog.getFieldName();
                String newValue = updateLog.getNewValue();
                for (Map<String, Object> datum : list) {
                    if (fieldName.equals(datum.get("fieldName"))) {
                        datum.put("value", convertValueByFormType(newValue, updateLog.getType()));
                    }
                }
            }
            return list;
        }
        data.forEach(map -> {
            map.put("authLevel", 2);
            Object type = map.get("type");
            if (FieldEnum.DETAIL_TABLE.getType().equals(type) ||
                    FieldEnum.EXAMINE_CAUSE.getType().equals(type) ||
                    FieldEnum.BUSINESS_CAUSE.getType().equals(type)) {
                map.put("tableLevel", 1);
            }

        });
        return data;
    }


    @Override
    public void updateFieldInfo(ExamineUpdateFieldBO examineUpdateFieldBO) {
        oaService.updateFieldInfo(examineUpdateFieldBO);
    }


    @Override
    public List<Map<String, Object>> queryExamineUpdateLog(List<ExamineFlowFieldUpdateLogBO> list) {
        return oaService.queryExamineUpdateLog(list).getData();
    }
}
